/* 
 * File:   main.cpp
 * Author: liuyi
 *
 * Created on January 27, 2010, 10:34 AM
 */

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <cassert>
#include <vector>
#include <ctime>

#include "Toolkit.h"
#include "MPLSH.h"
#include "Sample.h"
#include "SampleSpace.h"

using namespace std;

/**
 * MP-LSH parameter selection
 */
//void findParamGroup(int argc, char** argv) {
//	assert(argc == 12);
//
//	int offset = 1;
//	const char *filePath = argv[offset++];
//	const unsigned int dim = atoi(argv[offset++]);
//	const unsigned int MStart = atoi(argv[offset++]);
//	const unsigned int MStep = atoi(argv[offset++]);
//	const unsigned int MEnd = atoi(argv[offset++]);
//	const unsigned int LStart = atoi(argv[offset++]);
//	const unsigned int LStep = atoi(argv[offset++]);
//	const unsigned int LEnd = atoi(argv[offset++]);
//	const float WStart = atof(argv[offset++]);
//	const float WStep = atof(argv[offset++]);
//	const float WEnd = atof(argv[offset++]);
//
//	if(MStep == 0 || LStep == 0 || WStep == 0) {
//		assert(false);
//	}
//
//	vector<Sample *> sampleList;
//	SampleSpace sampleSpace(dim);
//
//	ifstream fin(filePath);
//	assert(fin);
//
//	sampleSpace.loadSampleFromStream(fin, sampleList);
//	fin.close();
//
//	vector<Sample *> subset;
//	const float samplingFactor = 0.1f;
//	const float acceptablePrecisionRate = 0.9f;
//	const int K = 1;
//
//	ParamGroup param = MPLSHParamSelector::select(sampleSpace, sampleList,
//			samplingFactor, acceptablePrecisionRate, K, MStart, MStep, MEnd,
//			LStart, LStep, LEnd, WStart, WStep, WEnd);
//
//	sampleSpace.deleteSampleArray(sampleList);
//}

void findNeighbors(SampleSpace &sampleSpace, vector<Sample *> &sampleList, const Sample &sample,
		vector<Sample *> &neighbors, unsigned int M, unsigned int L, float W, float **a, float **b) {

	MPLSH mplsh(sampleSpace, false);

	mplsh.assignParam(M, L, a, b, W);
	mplsh.insert(sampleList);

	mplsh.retrieveNeighbors(neighbors, sample);
}

/**
 * a sample of using MP-LSH method to find out neighbors
 */
void MPLSHSampleOfFindingNeighbors(int argc, char** argv) {
	assert(argc == 6);

	int offset = 1;
	const char *filePath = argv[offset++];
	const unsigned int dim = atoi(argv[offset++]);
	const unsigned int M = atoi(argv[offset++]);
	const unsigned int L = atoi(argv[offset++]);
	const float W = atof(argv[offset++]);

	float **a = new float*[L];
	float **b = new float*[L];
	int aLenInTable = M * dim;

	GuassRandom gr(1, 1);
	UniformRandom ur(0, W, false, false);

	for (unsigned int i = 0; i < L; ++i) {
		a[i] = new float[aLenInTable];
		b[i] = new float[M];

		gr.genRandomArray(a[i], aLenInTable);
		ur.genRandomArray(b[i], M);
	}

	vector<Sample *> sampleList;
	SampleSpace sampleSpace(dim);

	ifstream fin(filePath);
	assert(fin);

	sampleSpace.loadSampleFromStream(fin, sampleList);
	fin.close();

	vector<Sample *> neighbors;

	Sample *sample = sampleList.at(5);
	// ... assigns sample's feature

	findNeighbors(sampleSpace, sampleList, *sample, neighbors, M, L, W, a, b);

	cout << "the amount of neighbors: " << neighbors.size() << endl;

	// release memory
	for (unsigned int i = 0; i < L; ++i) {
		delete[] a[i];
		delete[] b[i];
	}
	delete[] a;
	delete[] b;

	sampleSpace.deleteSampleArray(sampleList);
	//sampleSpace.deleteSample(&sample);
}

int main(int argc, char** argv) {
	long seed = time(NULL);
	srand(seed);

	MPLSHSampleOfFindingNeighbors(argc, argv);

    return (EXIT_SUCCESS);
}
